﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation;
using Petzold.Media3D;

namespace WpfBrowserApplication1
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
        }
      

       
        private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2)
        {
            Vector3D v0 = new Vector3D(
                p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
            Vector3D v1 = new Vector3D(
                p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
            return Vector3D.CrossProduct(v0, v1);
        }

        private void ClearViewport()
        {
            ModelVisual3D m;
            for (int i = mainViewport.Children.Count - 1; i >= 0; i--)
            {
                m = (ModelVisual3D)mainViewport.Children[i];
                if (m.Content is DirectionalLight == false)
                    mainViewport.Children.Remove(m);
            }
        }
        PerspectiveCamera camera;
        private void SetCamera()
        {camera = (PerspectiveCamera)this.mainViewport.Camera;
          
            Point3D position = new Point3D(
                Convert.ToDouble(0),
                Convert.ToDouble(0),
                Convert.ToDouble(50)
            );
            Vector3D lookDirection = new Vector3D(
                Convert.ToDouble(0),
                Convert.ToDouble(0),
                Convert.ToDouble(-10)
            );
            camera.Position = position;
            camera.LookDirection = lookDirection;
        
        }
    

        private Point3D[] GetRandomTopographyPoints()
        {
            //create a 10x10 topography.
            Point3D[] points = new Point3D[100];
            Random r = new Random();
            double y;
            double denom = 1000;
            int count = 0;
            for (int z = 0; z < 10; z++)
            {
                for (int x = 0; x < 10; x++)
                {
                    System.Threading.Thread.Sleep(1);
                    y = Convert.ToDouble(r.Next(1, 999)) / denom;
                    points[count] = new Point3D(x, y, z);
                    count += 1;
                }
            }
            return points;
        }

        //每个母线10个点，一周36条母线共360个点
        Vector3D[] vertices = new Vector3D[360];
        void initVertices()
        {

	       
            for(int i=0;i<10;i++)
	        {
		        vertices[i]=  new Vector3D(i,i,0);
	        }
	        int angle=0;

             Matrix3D matrixRotate = new Matrix3D();
	        for(int i=1;i<36;i++)
	        {
		        angle=i*10;
		        matrixRotate.M11=1;
               double  myradian=Math.PI*angle/180;
		       matrixRotate=new Matrix3D(
                 1,                 0,                  0,                  0,
                 0, Math.Cos(myradian),Math.Sin(myradian),                  0,
                 0, -Math.Sin(myradian),Math.Cos(myradian),                 0,
                 0,                 0,                  0,                  1
                 
                 );
		    
		      
		     
		        for(int j=0;j<10;j++)
		        {
			        vertices[angle+j]=vertices[j]*matrixRotate;
		        }

	        }
        }
        private AxisAngleRotation3D _rotation = new AxisAngleRotation3D();
        private Transform3DGroup _transform;
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            ClearViewport();
            SetCamera();
            initVertices();
            MeshGeometry3D triangleMesh = new MeshGeometry3D();
            _transform = new Transform3DGroup();
       
            _transform.Children.Add(new RotateTransform3D(_rotation));
           
            Point3D point10 = new Point3D(0, 0, 0);
            Point3D point11 = new Point3D(1, 0, 0);
            Point3D point12 = new Point3D(0, 1, 0);
            for (int i = 0; i < 360;i++ )
            {
                triangleMesh.Positions.Add(new Point3D(vertices[i].X,vertices[i].Y,vertices[i].Z));
            }

            int j=0;
            for (int i = 0; i < 35; i++)
            {
          
                j = i * 10;
                for (int x = j; x < j + 9; x++)
                {
                    triangleMesh.TriangleIndices.Add(x);
                    triangleMesh.TriangleIndices.Add(x+1);
                    triangleMesh.TriangleIndices.Add(x + 10);

                    triangleMesh.TriangleIndices.Add(x + 10);
                    triangleMesh.TriangleIndices.Add(x + 1);
                    triangleMesh.TriangleIndices.Add(x + 11);
                }
            }

            for (int x = 350; x < 360; x++)
            {
                triangleMesh.TriangleIndices.Add(x);
                triangleMesh.TriangleIndices.Add(x + 1);
                triangleMesh.TriangleIndices.Add(x - 350);

                triangleMesh.TriangleIndices.Add(x - 350);
                triangleMesh.TriangleIndices.Add(x + 1);
                triangleMesh.TriangleIndices.Add(x - 349);
             

            }

      
           
            Material material = new DiffuseMaterial(
                new SolidColorBrush(Colors.Yellow));

            Material backmaterial = new DiffuseMaterial(
            new SolidColorBrush(Colors.Red));
            GeometryModel3D triangleModel = new GeometryModel3D(
                triangleMesh, material);
            camera.Transform = _transform;
            RotateTransform3D rt3d = new RotateTransform3D();
            
            triangleModel.BackMaterial = backmaterial;
         
            ModelVisual3D model = new ModelVisual3D();
           // model.Content = triangleModel;
            DirectionalLight myDirectionalLight = new DirectionalLight();
            myDirectionalLight.Color = Colors.Yellow;
            myDirectionalLight.Direction = new Vector3D(0, 0, -1);
            myDirectionalLight.Transform = _transform;
            Model3DGroup myModel3DGroup = new Model3DGroup();
            myModel3DGroup.Children.Add(myDirectionalLight);
            myModel3DGroup.Children.Add(triangleModel);
            model.Content = myModel3DGroup;
            this.mainViewport.Children.Add(model);
         
            

            //NameScope.SetNameScope(this, new NameScope());
            //model.Transform = new TranslateTransform3D();




           // this.RegisterName("axisRotation3D", axisAngleRotation3D);


   
        }

      

          bool isTracking;
        Point3D pointOriginal;
        TranslateTransform3D transOriginal;
        TranslateTransform3D transTracking;

        //右键原始点
        Point _previousPosition2D;
        Vector3D _previousPosition3D;
     
    

        // Mouse wheel moves forward and backward along Z axis.
        double z = 50;
        protected override void OnMouseWheel(MouseWheelEventArgs args)
        {
            base.OnMouseWheel(args);

     
            z=z+args.Delta / 1200.0;
            Point3D position = new Point3D(
              Convert.ToDouble(0),
              Convert.ToDouble(0),
              Convert.ToDouble(z)
          );

            camera.Position = position;
        }

    
    
        // Abort the tracking operation.
        protected override void OnPreviewTextInput(TextCompositionEventArgs args)
        {
            base.OnPreviewTextInput(args);

            if (!isTracking)
                return;

            // End mouse tracking with press of Escape key.
            if (args.Text.IndexOf('\x1B') != -1)
                ReleaseMouseCapture();
        }

   

      
      

       
        private Vector3D ProjectToTrackball(double width, double height, Point point)
        {
            double x = point.X / (width / 2);    // Scale so bounds map to [0,0] - [2,2]
            double y = point.Y / (height / 2);

            x = x - 1;                           // Translate 0,0 to the center
            y = 1 - y;                           // Flip so +Y is up instead of down

            double z2 = 1 - x * x - y * y;       // z^2 = 1 - x^2 - y^2
            double z = z2 > 0 ? Math.Sqrt(z2) : 0;

            return new Vector3D(x, y, z);
        }
        private void Track(Point currentPosition)
        {
            Vector3D currentPosition3D = ProjectToTrackball(
                this.mainViewport.ActualWidth, this.mainViewport.ActualHeight, currentPosition);

            Vector3D axis = Vector3D.CrossProduct(_previousPosition3D, currentPosition3D);
            double angle = Vector3D.AngleBetween(_previousPosition3D, currentPosition3D);
            if (axis==null || angle==null || angle==0) return;
            Quaternion delta = new Quaternion(axis, -angle);

            // Get the current orientantion from the RotateTransform3D
            AxisAngleRotation3D r = _rotation;
            Quaternion q = new Quaternion(_rotation.Axis, _rotation.Angle);

            // Compose the delta with the previous orientation
            q *= delta;

            // Write the new orientation back to the Rotation3D
            _rotation.Axis = q.Axis;
            _rotation.Angle = q.Angle;

            _previousPosition3D = currentPosition3D;
        }
            

        private void mainViewport_MouseDown(object sender, MouseButtonEventArgs args)
        {
            Mouse.Capture(this.mainViewport, CaptureMode.Element);
            _previousPosition2D = args.GetPosition(this.mainViewport);
            _previousPosition3D = ProjectToTrackball(
              this.mainViewport.ActualWidth,
              this.mainViewport.ActualHeight,
              _previousPosition2D);
        }

        private void mainViewport_MouseMove(object sender, MouseEventArgs args)
        {
            Point ptMouse = args.GetPosition(this.mainViewport);
          
            // Get the mouse position and adjust the translate transform.
            if (args.LeftButton == MouseButtonState.Pressed)
            {

                Track(ptMouse);
                _previousPosition2D = ptMouse;
            }
            else if (args.RightButton == MouseButtonState.Pressed)
            {
                z = z + (ptMouse.Y - _previousPosition2D.Y) / 10;

                Point3D position = new Point3D(
                 Convert.ToDouble(0),
                 Convert.ToDouble(0),
                 Convert.ToDouble(z)
                 );
                _previousPosition2D = ptMouse;

                camera.Position = position;
            }
        }

        private void mainViewport_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Mouse.Capture(this.mainViewport, CaptureMode.None);
        }
    }
}
